//
//  Updater.m
//  rss_reader
//
//  Created by Oleg Soldatoff on 5/4/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#import "Updater.h"
#import <sqlite3.h>

@implementation Updater
static Updater *sharedUpdater = nil;


- (void) configBase {
  
  if (sqlite3_threadsafe() > 0) {
    int retCode = sqlite3_config(SQLITE_CONFIG_SERIALIZED);
    if (retCode == SQLITE_OK) {
      NSLog(@"Can now use sqlite on multiple threads, using the same connection");
    } else {
      NSLog(@"setting sqlite thread safe mode to serialized failed!!! return code: %d", retCode);
    }
  } else {
    NSLog(@"Your SQLite database is not compiled to be threadsafe.");
  }
  
  
  
}



+ (Updater *)sharedUpdater {
  
  if (sharedUpdater == nil) {
    sharedUpdater = [[Updater alloc] init];
  }
  return sharedUpdater;
  
}

- (void) dealloc {
  
  [[NSNotificationCenter defaultCenter] removeObserver:self]; 
  dispatch_release( exampleQueue );
  [super dealloc];
  
}


- (NSString *) databasePath {
  
  // Get the documents directory
  NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  NSString *docsDir = [dirPaths objectAtIndex:0];
  //NSLog(@"HOME - %@", docsDir);
  // Build the path to the database file
  return [[[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent: @"feeds.db"]]autorelease];
  
}

- (id)init
{
  NSLog(@"NEW CLASSSSSS");
  self = [super init];
  if (self) {
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(pocessNotification:)  
                                                 name:@"xmlRecieved" 
                                               object:nil];
    
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(pocessNotification:)  
                                                 name:@"ErrorInNetwork" 
                                               object:nil]; 
    
  }
  exampleQueue = dispatch_queue_create( "com.example.update.news", NULL );
  
  return self;
}






-(void) updateAllFromInet {
  
  
  
  
  NSMutableArray *tmpFeeds = [self baseFeedsForSiteID: 0];
  [tmpFeeds retain];
  
  dispatch_async( exampleQueue, ^{
    UIApplication* app = [UIApplication sharedApplication];
    app.networkActivityIndicatorVisible = YES;
    NSLog(@"Dispatch async started");
    
    
    for (NSDictionary *feedDic in tmpFeeds) {
      [self startTheBackgroundJob: feedDic];
    }
    NSLog(@"For ended");
    
    dispatch_sync( dispatch_get_main_queue(), ^{
      
      [[NSNotificationCenter defaultCenter] postNotificationName:@"BaseUpdated" object:self];
      app.networkActivityIndicatorVisible = NO;
      NSLog(@"ReloadTable");
    });
  });
  [tmpFeeds release];
  
}



- (void)startTheBackgroundJob: (NSDictionary *) feedDic  {  
  
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];  
  NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
  NSLog(@"startTheBackgroundJob feed URL - %@", feedDic);
  [[[[Network alloc]init]autorelease]giveXML:feedDic];
  
  //[runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
  while ([runLoop runMode:NSDefaultRunLoopMode
               beforeDate:[NSDate distantFuture]]);
  [pool release]; 
  NSLog(@"Thread stopped");
}  

- (void) pocessNotification:(NSNotification *) notification { 
  
  if ( [[notification name] isEqualToString:@"xmlRecieved"] )   { 
    
    NSLog(@"%@", [[notification userInfo] valueForKey:@"ID"]);
    
    Network * netw = [notification object];
    
    [self saveArticles: [XMLParser arrayWithItems:[netw receivedData]]
               forFeed: [[notification userInfo] valueForKey:@"ID"]];
    
  } else if ( [[notification name] isEqualToString:@"ErrorInNetwork"] ) {
    
    [[[[UIAlertView alloc]initWithTitle:@"Network error"
                                message:[NSString stringWithFormat:@"Problems while connecting to %@", [[notification userInfo] valueForKey:@"URL"] ] 
                               delegate:nil 
                      cancelButtonTitle:@"Ok" 
                      otherButtonTitles: nil]autorelease]show];
    
  }
  
  
}  




- (NSMutableArray *) baseFeedsForSiteID:(NSInteger) siteID {
  
  NSString *querySQL;
  sqlite3 *feedsDB;
  NSMutableArray *baseFeeds; 
  
  baseFeeds = [[[NSMutableArray alloc]init]autorelease];
  const char *dbpath = [[self databasePath] UTF8String];
  sqlite3_stmt    *statement;
  [self configBase];

  if (sqlite3_open(dbpath, &feedsDB) == SQLITE_OK)
  {
    if ( 0 != siteID ) querySQL = [NSString stringWithFormat:@"SELECT * FROM FEEDS WHERE SITE_ID = %d", siteID];
    else querySQL = [NSString stringWithFormat:@"SELECT * FROM FEEDS"];
    
    const char *query_stmt = [querySQL UTF8String];
    
    if (sqlite3_prepare_v2(feedsDB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
    {
      while (sqlite3_step(statement) == SQLITE_ROW)
      {
        //Feeds (ID, SITE_ID, URL, NAME, STATUS)
        NSNumber *feedID = [NSNumber numberWithInt: sqlite3_column_int(statement, 0)];
        NSNumber *siteID = [NSNumber numberWithInt: sqlite3_column_int(statement, 1)];
        NSString *feedURL = [[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 2)]autorelease];
        NSString *feedName = [[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 3)]autorelease];
        NSNumber *feedSTATUS = [NSNumber numberWithInt: sqlite3_column_int(statement, 4)];
        
        NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:
                             feedID,     @"ID", 
                             siteID,     @"SITE_ID", 
                             feedURL,    @"URL", 
                             feedName,   @"NAME", 
                             feedSTATUS, @"STATUS", nil];
        
        [baseFeeds addObject:dic];        
      } 
      sqlite3_finalize(statement);
    }
    sqlite3_close(feedsDB);
  }
  
  return baseFeeds;
  
  
  
}




- (void) saveArticles: (NSArray*) articlesArr forFeed: (NSNumber*) feedID {
  
  
  NSMutableString *stringWithURLsOfArticles = [[[NSMutableString alloc]init]autorelease];
  
  for (NSDictionary *dicArticle in articlesArr) { 
    
    if ( [articlesArr lastObject] == dicArticle )
      [stringWithURLsOfArticles appendFormat:@"'%@'",   [dicArticle valueForKey: @"link"]];
    else    [stringWithURLsOfArticles appendFormat:@"'%@', ", [dicArticle valueForKey: @"link"]];
    
  }
  
  //Delete articles
  NSString *deleteArticles = [NSString stringWithFormat:@"DELETE FROM ARTICLES WHERE STATUS !=1 AND FEED_ID = %@ AND URL NOT IN (%@);", feedID, stringWithURLsOfArticles];
  
  //NSLog(@"DELEET ARTICLES - %@",deleteArticles );
  [self sqliteDo:deleteArticles];
  
  //Add articles
  for (NSDictionary *dicArticleOfFeed in articlesArr) {
    
    NSString *insertArticle = [NSString stringWithFormat:@"INSERT INTO ARTICLES (FEED_ID, URL, NAME, DESC, DATE, STATUS) SELECT ?, ?, ?, ?, ?, ? WHERE NOT EXISTS (SELECT 1 FROM ARTICLES WHERE URL LIKE ? AND  FEED_ID = ?);"];
    //NSLog(@"%@", insertArticle);
    [self sqliteDo:insertArticle, 
     feedID, 
     [dicArticleOfFeed valueForKey: @"link"],       
     [dicArticleOfFeed valueForKey: @"title"],
     [dicArticleOfFeed valueForKey: @"description"],
     [dicArticleOfFeed valueForKey: @"pubdate"],
     [NSNumber numberWithInt: 0], 
     [dicArticleOfFeed valueForKey: @"link"],
     feedID];
  }
}


- (BOOL) sqliteDo: (NSString *) sqlQuery, ... {
  
  BOOL result;
  int param_count;
  sqlite3_stmt    *statement;
  sqlite3 *feedsDB;
  
  const char *dbpath = [[self databasePath] UTF8String];
  [self configBase];

  if (sqlite3_open(dbpath, &feedsDB) == SQLITE_OK)
  {
    const char *query_stmt = [sqlQuery UTF8String];
    sqlite3_prepare_v2(feedsDB, query_stmt, -1, &statement, NULL);
    
    va_list args;
    va_start(args, sqlQuery);
    
    if ((param_count = sqlite3_bind_parameter_count(statement))) {
      for (int i = 0; i < param_count; i++) {
        id o = va_arg(args, id);
        
        // determine the type of the argument
        if (o == nil) {
          sqlite3_bind_null(statement, i + 1);
        } else if ([o respondsToSelector:@selector(objCType)]) {
          if (strchr("islISLB", *[o objCType])) { // integer
            sqlite3_bind_int(statement, i + 1, [o intValue]);
          } else if (strchr("fd", *[o objCType])) {   // double
            sqlite3_bind_double(statement, i + 1, [o doubleValue]);
          } else {    // unhandled types
            NSLog(@"bindSQL: Unhandled objCType: %s", [o objCType]);
            statement = NULL;
            return NO;
          }
        } else if ([o respondsToSelector:@selector(UTF8String)]) { // string
          sqlite3_bind_text(statement, i + 1, [o UTF8String], -1, SQLITE_TRANSIENT);
        } else {    // unhhandled type
          NSLog(@"bindSQL: Unhandled parameter type: %@", [o class]);
          statement = NULL;
          return NO;
        }
      }
    }
    
    va_end(args);
    
    if (sqlite3_step(statement) == SQLITE_DONE)
    {
      //NSLog(@"DB updated");
      result = YES;
    } else {
      NSLog(@"Failed to update DB");
      NSLog(@"%@", sqlQuery);
      result = NO;
    }
    sqlite3_finalize(statement);
  }
  sqlite3_close(feedsDB);
  
  return result;
}


@end
